<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>💥川北医学院22级班长大大们🎆</title>

    <meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
    <meta name="mobile-web-app-capable" content="yes">
    <meta name="apple-mobile-web-app-capable" content="yes">
    <meta name="theme-color" content="#000000">
    <link rel="shortcut icon" type="image/png"
        href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon-v2.png">
    <link rel="icon" type="image/png"
        href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon-v2.png">
    <link rel="apple-touch-icon-precomposed"
        href="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon-v2.png">
    <meta name="msapplication-TileColor" content="#000000">
    <meta name="msapplication-TileImage"
        content="https://s3-us-west-2.amazonaws.com/s.cdpn.io/329180/firework-burst-icon-v2.png">
    <style>
        * {
            margin: 0;
            padding: 0;
            border: 0;
            font-size: 100%;
            font: inherit;
            vertical-align: baseline;
            touch-action: none;
        }

        article,
        aside,
        details,
        figcaption,
        figure,
        footer,
        header,
        hgroup,
        menu,
        nav,
        section {
            display: block
        }

        body {
            line-height: 1
        }

        ol,
        ul {
            list-style: none
        }

        blockquote,
        q {
            quotes: none
        }

        blockquote:before,
        blockquote:after,
        q:before,
        q:after {
            content: '';
            content: none
        }

        table {
            border-collapse: collapse;
            border-spacing: 0
        }

        * {
            position: relative;
            box-sizing: border-box;
        }

        html,
        body {
            height: 100%;
        }

        html {
            background-color: #000;
        }

        body {
            overflow: hidden;
            color: rgba(255, 255, 255, 0.5);
            font-family: "Russo One", arial, sans-serif;
            line-height: 1.25;
            letter-spacing: 0.06em;
        }

        .hide {
            opacity: 0;
            visibility: hidden;
        }

        .remove {
            display: none !important;
        }

        .blur {
            -webkit-filter: blur(12px);
            filter: blur(12px);
        }

        .container {
            height: 100%;
            display: -webkit-box;
            display: flex;
            -webkit-box-pack: center;
            justify-content: center;
            -webkit-box-align: center;
            align-items: center;
        }

        .loading-init {
            width: 100%;
            align-self: center;
            text-align: center;
            text-transform: uppercase;
        }

        .loading-init__header {
            font-size: 2.2em;
        }

        .loading-init__status {
            margin-top: 1em;
            font-size: 0.8em;
            opacity: 0.75;
        }

        .stage-container {
            overflow: hidden;
            box-sizing: initial;
            border: 1px solid #222;
            margin: -1px;
        }

        @media (max-width: 840px) {
            .stage-container {
                border: none;
                margin: 0;
            }
        }

        .canvas-container {
            width: 100%;
            height: 100%;
            -webkit-transition: -webkit-filter 0.3s;
            transition: -webkit-filter 0.3s;
            transition: filter 0.3s;
            transition: filter 0.3s, -webkit-filter 0.3s;
        }

        .canvas-container canvas {
            position: absolute;
            mix-blend-mode: lighten;
            -webkit-transform: translateZ(0);
            transform: translateZ(0);
        }

        .controls {
            /* display: none !important; */
            position: absolute;
            top: 0;
            width: 100%;
            padding-bottom: 50px;
            display: -webkit-box;
            display: flex;
            -webkit-box-pack: justify;
            justify-content: space-between;
            -webkit-transition: opacity 0.3s, visibility 0.3s;
            transition: opacity 0.3s, visibility 0.3s;
        }

        @media (min-width: 840px) {
            .controls {
                visibility: visible;
            }

            .controls.hide:hover {
                opacity: 1;
            }
        }

        .menu {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            background-color: rgba(0, 0, 0, 0.42);
            -webkit-transition: opacity 0.3s, visibility 0.3s;
            transition: opacity 0.3s, visibility 0.3s;
        }

        .menu__inner-wrap {
            display: -webkit-box;
            display: flex;
            -webkit-box-orient: vertical;
            -webkit-box-direction: normal;
            flex-direction: column;
            -webkit-box-pack: center;
            justify-content: center;
            -webkit-box-align: center;
            align-items: center;
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            -webkit-transition: opacity 0.3s;
            transition: opacity 0.3s;
        }

        .menu__header {
            margin-top: auto;
            margin-bottom: 8px;
            padding-top: 16px;
            font-size: 2em;
            text-transform: uppercase;
        }

        .menu__subheader {
            margin-bottom: auto;
            padding-bottom: 12px;
            font-size: 0.86em;
            opacity: 0.8;
        }

        .menu form {
            width: 100%;
            max-width: 400px;
            padding: 0 10px;
            overflow: auto;
            -webkit-overflow-scrolling: touch;
        }

        .menu .form-option {
            display: -webkit-box;
            display: flex;
            -webkit-box-align: center;
            align-items: center;
            margin: 16px 0;
            -webkit-transition: opacity 0.3s;
            transition: opacity 0.3s;
        }

        .menu .form-option label {
            display: block;
            width: 50%;
            padding-right: 12px;
            text-align: right;
            text-transform: uppercase;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
        }

        .menu .form-option--select select {
            display: block;
            width: 50%;
            height: 30px;
            font-size: 1rem;
            font-family: "Russo One", arial, sans-serif;
            color: rgba(255, 255, 255, 0.5);
            letter-spacing: 0.06em;
            background-color: transparent;
            border: 1px solid rgba(255, 255, 255, 0.5);
        }

        .menu .form-option--select select option {
            background-color: black;
        }

        .menu .form-option--checkbox input {
            display: block;
            width: 26px;
            height: 26px;
            margin: 0;
            opacity: 0.5;
        }

        @media (max-width: 840px) {

            .menu .form-option select,
            .menu .form-option input {
                outline: none;
            }
        }

        .close-menu-btn {
            position: absolute;
            top: 0;
            right: 0;
        }

        .btn {
            opacity: 0.16;
            width: 50px;
            height: 50px;
            display: -webkit-box;
            display: flex;
            -webkit-user-select: none;
            -moz-user-select: none;
            -ms-user-select: none;
            user-select: none;
            cursor: default;
            -webkit-transition: opacity 0.3s;
            transition: opacity 0.3s;
        }

        .btn--bright {
            opacity: 0.5;
        }

        @media (min-width: 840px) {
            .btn:hover {
                opacity: 0.32;
            }

            .btn--bright:hover {
                opacity: 0.75;
            }
        }

        .btn svg {
            display: block;
            margin: auto;
        }

        .credits {
            margin-top: auto;
            margin-bottom: 10px;
            padding-top: 6px;
            font-size: 0.8em;
            opacity: 0.75;
        }

        .credits a {
            color: rgba(255, 255, 255, 0.5);
            text-decoration: none;
        }

        .credits a:hover,
        .credits a:active {
            color: rgba(255, 255, 255, 0.75);
            text-decoration: underline;
        }

        .help-modal {
            display: -webkit-box;
            display: flex;
            -webkit-box-pack: center;
            justify-content: center;
            -webkit-box-align: center;
            align-items: center;
            position: fixed;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            visibility: hidden;
            -webkit-transition-property: visibility;
            transition-property: visibility;
            -webkit-transition-duration: 0.25s;
            transition-duration: 0.25s;
        }

        .help-modal__overlay {
            position: absolute;
            top: 0;
            bottom: 0;
            left: 0;
            right: 0;
            opacity: 0;
            -webkit-transition-property: opacity;
            transition-property: opacity;
            -webkit-transition-timing-function: ease-in;
            transition-timing-function: ease-in;
            -webkit-transition-duration: 0.25s;
            transition-duration: 0.25s;
        }

        .help-modal__dialog {
            display: -webkit-box;
            display: flex;
            -webkit-box-orient: vertical;
            -webkit-box-direction: normal;
            flex-direction: column;
            -webkit-box-align: center;
            align-items: center;
            max-width: 400px;
            max-height: calc(100vh - 100px);
            margin: 10px;
            padding: 20px;
            border-radius: 0.3em;
            background-color: rgba(0, 0, 0, 0.4);
            opacity: 0;
            -webkit-transform: scale(0.9, 0.9);
            transform: scale(0.9, 0.9);
            -webkit-transition-property: opacity, -webkit-transform;
            transition-property: opacity, -webkit-transform;
            transition-property: opacity, transform;
            transition-property: opacity, transform, -webkit-transform;
            -webkit-transition-timing-function: ease-in;
            transition-timing-function: ease-in;
            -webkit-transition-duration: 0.25s;
            transition-duration: 0.25s;
        }

        @media (min-width: 840px) {
            .help-modal__dialog {
                font-size: 1.25rem;
                max-width: 500px;
            }
        }

        .help-modal__header {
            font-size: 1.75em;
            text-transform: uppercase;
            text-align: center;
        }

        .help-modal__body {
            overflow-y: auto;
            -webkit-overflow-scrolling: touch;
            margin: 1em 0;
            padding: 1em 0;
            border-top: 1px solid rgba(255, 255, 255, 0.25);
            border-bottom: 1px solid rgba(255, 255, 255, 0.25);
            line-height: 1.5;
            color: rgba(255, 255, 255, 0.75);
        }

        .help-modal__close-btn {
            flex-shrink: 0;
            outline: none;
            border: none;
            border-radius: 2px;
            padding: 0.25em 0.75em;
            margin-top: 0.36em;
            font-family: "Russo One", arial, sans-serif;
            font-size: 1em;
            color: rgba(255, 255, 255, 0.5);
            text-transform: uppercase;
            letter-spacing: 0.06em;
            background-color: rgba(255, 255, 255, 0.25);
            -webkit-transition: color 0.3s, background-color 0.3s;
            transition: color 0.3s, background-color 0.3s;
        }

        .help-modal__close-btn:hover,
        .help-modal__close-btn:active,
        .help-modal__close-btn:focus {
            color: #FFF;
            background-color: #09F;
        }

        .help-modal.active {
            visibility: visible;
            -webkit-transition-duration: 0.4s;
            transition-duration: 0.4s;
        }

        .help-modal.active .help-modal__overlay {
            opacity: 1;
            -webkit-transition-timing-function: ease-out;
            transition-timing-function: ease-out;
            -webkit-transition-duration: 0.4s;
            transition-duration: 0.4s;
        }

        .help-modal.active .help-modal__dialog {
            opacity: 1;
            -webkit-transform: scale(1, 1);
            transform: scale(1, 1);
            -webkit-transition-timing-function: ease-out;
            transition-timing-function: ease-out;
            -webkit-transition-duration: 0.4s;
            transition-duration: 0.4s;
        }

        .hide {
            display: none !important;
        }

        .type_words {
            padding: 60px 80px 20px 0px;
            position: absolute;
            top: 0px;
            left: 10px;
            z-index: 500;
            color: #ffffff;
            font-size: 14px;
        }
    </style>
    <script src="https://wechat-small-app.oss-cn-hangzhou.aliyuncs.com/bbp/yh/js/lib/jquery.min.js"
        type="text/javascript"></script>
    <script>
        var shouci = true;
        console.log(shouci);
        function bodyPlayMusic() {
            if (shouci) {
                shouci = false;
                audio.play();
                console.log(shouci);
            }
        };

    </script>
</head>
<!-- onclick="bodyPlayMusic()" -->

<body>

    <a href="https://mp.weixin.qq.com/s/DhiMtvprg1JTiDTg51trFA" class="hide_buttom"
        style="position: fixed;top: 4%;right: 10px;width: 35px;height: 35px;z-index: 999;background: #696969;border-radius: 50%;padding: 1.0px;text-align: center;color: #ddd;text-decoration: none;   clear: both; line-height: 35px; 	margin:auto;   font-size: 13px;   ">制作</a>

    <a href="https://mp.weixin.qq.com/s/my3ZmuPktbfpw2txYgrubA" class="hide_buttom"
        style="position: fixed;top: 10%;right: 10px;width: 35px;height: 35px;z-index: 999;background: #696969;border-radius: 50%;padding: 1.0px;text-align: center;color: #ddd;text-decoration: none;   clear: both; line-height: 35px; 	margin:auto;   font-size: 13px;   ">更多</a>

    <!-- clickMusic() -->
    <img id="music_ico" onclick="" alt="" style=" display: inline; float: right;  ">

    <audio id="audioDom" src="https://sf6-cdn-tos.douyinstatic.com/obj/ies-music/7170534431801838367.mp3" preload="auto"
        loop="loop"></audio>

    <div id="yhBtn"
        style="position:fixed;top:0;left:0;width:100%;height:100%;z-index:999;display:flex;flex-direction:column;justify-content:center;align-items:center;color:#fff ; font-size:15px">
        <p>💥点爆</p>
        <img style="width:64px;margin-bottom:24px "
            src="https://p9.toutiaoimg.com/img/tos-cn-i-qvj2lq49k0/060990dac854444ab7a927b5b3311fe4~tplv-tt-shrink:640:0.image">

    </div>

    <div style="height: 0; width: 0; position: absolute; visibility: hidden;">
        <svg xmlns="http://www.w3.org/2000/svg">
            <symbol id="icon-play" viewbox="0 0 24 24">
                <path d="M8 5v14l11-7z"></path>
            </symbol>
            <symbol id="icon-pause" viewbox="0 0 24 24">
                <path d="M6 19h4V5H6v14zm8-14v14h4V5h-4z"></path>
            </symbol>
            <symbol id="icon-close" viewbox="0 0 24 24">
                <path
                    d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z">
                </path>
            </symbol>
            <symbol id="icon-settings" viewbox="0 0 24 24">
                <path
                    d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z">
                </path>
            </symbol>
            <symbol id="icon-sound-on" viewbox="0 0 24 24">
                <path
                    d="M3 9v6h4l5 5V4L7 9H3zm13.5 3c0-1.77-1.02-3.29-2.5-4.03v8.05c1.48-.73 2.5-2.25 2.5-4.02zM14 3.23v2.06c2.89.86 5 3.54 5 6.71s-2.11 5.85-5 6.71v2.06c4.01-.91 7-4.49 7-8.77s-2.99-7.86-7-8.77z">
                </path>
            </symbol>
            <symbol id="icon-sound-off" viewbox="0 0 24 24">
                <path
                    d="M16.5 12c0-1.77-1.02-3.29-2.5-4.03v2.21l2.45 2.45c.03-.2.05-.41.05-.63zm2.5 0c0 .94-.2 1.82-.54 2.64l1.51 1.51C20.63 14.91 21 13.5 21 12c0-4.28-2.99-7.86-7-8.77v2.06c2.89.86 5 3.54 5 6.71zM4.27 3L3 4.27 7.73 9H3v6h4l5 5v-6.73l4.25 4.25c-.67.52-1.42.93-2.25 1.18v2.06c1.38-.31 2.63-.95 3.69-1.81L19.73 21 21 19.73l-9-9L4.27 3zM12 4L9.91 6.09 12 8.18V4z">
                </path>
            </symbol>
        </svg>
    </div>

    <!-- App -->
    <div class="container">
        <div class="loading-init">
            <div class="loading-init__header"></div>
            <div class="loading-init__status"></div>
        </div>
        <div class="stage-container remove">
            <div class="page_two hide">
                <div class="type_words" id="contents"></div>
            </div>
            <div class="canvas-container">
                <canvas id="trails-canvas"></canvas>
                <canvas id="main-canvas"></canvas>
            </div>

            <div class="menu hide">
                <div class="menu__inner-wrap">
                    <div class="btn btn--bright close-menu-btn">
                        <svg fill="white" width="24" height="24">
                            <use href="#icon-close" xlink:href="#icon-close"></use>
                        </svg>
                    </div>

                    <div class="menu__header">设置</div>
                    <!--<div class="menu__subheader"><br>微信公众号：期待晨光-->
                    <!--</div>-->
                    <form>
                        <div class="form-option form-option--select">
                            <label class="shell-type-label">烟花类型</label>
                            <select class="shell-type"></select>
                        </div>
                        <div class="form-option form-option--select">
                            <label class="shell-size-label">烟花大小</label>
                            <select class="shell-size"></select>
                        </div>
                        <div class="form-option form-option--select">
                            <label class="quality-ui-label">画质</label>
                            <select class="quality-ui"></select>
                        </div>
                        <div class="form-option form-option--select">
                            <label class="sky-lighting-label">天空照明</label>
                            <select class="sky-lighting"></select>
                        </div>
                        <div class="form-option form-option--select">
                            <label class="scaleFactor-label">规模</label>
                            <select class="scaleFactor"></select>
                        </div>
                        <div class="form-option form-option--checkbox">
                            <label class="auto-launch-label">自动发射</label>
                            <input class="auto-launch" type="checkbox">
                        </div>
                        <div class="form-option form-option--checkbox form-option--finale-mode">
                            <label class="finale-mode-label">结局模式</label>
                            <input class="finale-mode" type="checkbox">
                        </div>
                        <div class="form-option form-option--checkbox">
                            <label class="hide-controls-label">隐藏控制器</label>
                            <input class="hide-controls" type="checkbox">
                        </div>
                        <div class="form-option form-option--checkbox form-option--fullscreen">
                            <label class="fullscreen-label">全屏</label>
                            <input class="fullscreen" type="checkbox">
                        </div>
                        <div class="form-option form-option--checkbox">
                            <label class="long-exposure-label">打开快门</label>
                            <input class="long-exposure" type="checkbox">
                        </div>
                    </form>
                </div>
            </div>
        </div>
        <div class="help-modal">
            <div class="help-modal__overlay"></div>
            <div class="help-modal__dialog">
                <div class="help-modal__header"></div>
                <div class="help-modal__body"></div>
                <button type="button" class="help-modal__close-btn">关闭</button>
            </div>
        </div>
    </div>

    <!-- partial -->
    <script type="text/javascript" src="https://s9.cnzz.com/z_stat.php?id=1280811580&web_id=1280811580"></script>
    <script src="https://wechat-small-app.oss-cn-hangzhou.aliyuncs.com/bbp/yh/js/lib/jquery.min.js"
        type="text/javascript"></script>
    <script>
        // fscreen@1.0.1.js
        // A manual UMD build of Fscreen: https://github.com/rafrex/fscreen
        (function (global) {
            'use strict';

            var key = {
                fullscreenEnabled: 0,
                fullscreenElement: 1,
                requestFullscreen: 2,
                exitFullscreen: 3,
                fullscreenchange: 4,
                fullscreenerror: 5
            };

            var webkit = ['webkitFullscreenEnabled', 'webkitFullscreenElement', 'webkitRequestFullscreen', 'webkitExitFullscreen', 'webkitfullscreenchange', 'webkitfullscreenerror'];

            var moz = ['mozFullScreenEnabled', 'mozFullScreenElement', 'mozRequestFullScreen', 'mozCancelFullScreen', 'mozfullscreenchange', 'mozfullscreenerror'];

            var ms = ['msFullscreenEnabled', 'msFullscreenElement', 'msRequestFullscreen', 'msExitFullscreen', 'MSFullscreenChange', 'MSFullscreenError'];

            // so it doesn't throw if no window or document
            var doc = typeof window !== 'undefined' && typeof window.document !== 'undefined' ? window.document : {};

            var vendor = 'fullscreenEnabled' in doc && Object.keys(key) || webkit[0] in doc && webkit || moz[0] in doc && moz || ms[0] in doc && ms || [];

            var fscreen = {
                requestFullscreen: function requestFullscreen(element) {
                    return element[vendor[key.requestFullscreen]]();
                },
                requestFullscreenFunction: function requestFullscreenFunction(element) {
                    return element[vendor[key.requestFullscreen]];
                },
                get exitFullscreen() {
                    return doc[vendor[key.exitFullscreen]].bind(doc);
                },
                addEventListener: function addEventListener(type, handler, options) {
                    return doc.addEventListener(vendor[key[type]], handler, options);
                },
                removeEventListener: function removeEventListener(type, handler) {
                    return doc.removeEventListener(vendor[key[type]], handler);
                },
                get fullscreenEnabled() {
                    return Boolean(doc[vendor[key.fullscreenEnabled]]);
                },
                set fullscreenEnabled(val) { },
                get fullscreenElement() {
                    return doc[vendor[key.fullscreenElement]];
                },
                set fullscreenElement(val) { },
                get onfullscreenchange() {
                    return doc[('on' + vendor[key.fullscreenchange]).toLowerCase()];
                },
                set onfullscreenchange(handler) {
                    return doc[('on' + vendor[key.fullscreenchange]).toLowerCase()] = handler;
                },
                get onfullscreenerror() {
                    return doc[('on' + vendor[key.fullscreenerror]).toLowerCase()];
                },
                set onfullscreenerror(handler) {
                    return doc[('on' + vendor[key.fullscreenerror]).toLowerCase()] = handler;
                }
            };

            global.fscreen = fscreen;
        })(window);
        // Stage@0.1.4.js
        const Ticker = (function TickerFactory(window) {
            'use strict';

            const Ticker = {};
            // public
            // will call function reference repeatedly once registered, passing elapsed time and a lag multiplier as parameters
            Ticker.addListener = function addListener(callback) {
                if (typeof callback !== 'function') throw ('Ticker.addListener() requires a function reference passed for a callback.');

                listeners.push(callback);

                // start frame-loop lazily
                if (!started) {
                    started = true;
                    queueFrame();
                }
            };

            // private
            let started = false;
            let lastTimestamp = 0;
            let listeners = [];

            // queue up a new frame (calls frameHandler)
            function queueFrame() {
                if (window.requestAnimationFrame) {
                    requestAnimationFrame(frameHandler);
                } else {
                    webkitRequestAnimationFrame(frameHandler);
                }
            }

            function frameHandler(timestamp) {
                let frameTime = timestamp - lastTimestamp;
                lastTimestamp = timestamp;
                // make sure negative time isn't reported (first frame can be whacky)
                if (frameTime < 0) {
                    frameTime = 17;
                }
                // - cap minimum framerate to 15fps[~68ms] (assuming 60fps[~17ms] as 'normal')
                else if (frameTime > 68) {
                    frameTime = 68;
                }

                // fire custom listeners
                listeners.forEach(listener => listener.call(window, frameTime, frameTime / 16.6667));

                // always queue another frame
                queueFrame();
            }
            return Ticker;
        })(window);
        const Stage = (function StageFactory(window, document, Ticker) {
            'use strict';

            // Track touch times to prevent redundant mouse events.
            let lastTouchTimestamp = 0;

            // Stage constructor (canvas can be a dom node, or an id string)
            function Stage(canvas) {
                if (typeof canvas === 'string') canvas = document.getElementById(canvas);

                // canvas and associated context references
                this.canvas = canvas;
                this.ctx = canvas.getContext('2d');

                // Prevent gestures on stages (scrolling, zooming, etc)
                this.canvas.style.touchAction = 'none';

                // physics speed multiplier: allows slowing down or speeding up simulation (must be manually implemented in physics layer)
                this.speed = 1;

                // devicePixelRatio alias (should only be used for rendering, physics shouldn't care)
                // avoids rendering unnecessary pixels that browser might handle natively via CanvasRenderingContext2D.backingStorePixelRatio
                this.dpr = Stage.disableHighDPI ? 1 : ((window.devicePixelRatio || 1) / (this.ctx.backingStorePixelRatio || 1));

                // canvas size in DIPs and natural pixels
                this.width = canvas.width;
                this.height = canvas.height;
                this.naturalWidth = this.width * this.dpr;
                this.naturalHeight = this.height * this.dpr;

                // size canvas to match natural size
                if (this.width !== this.naturalWidth) {
                    this.canvas.width = this.naturalWidth;
                    this.canvas.height = this.naturalHeight;
                    this.canvas.style.width = this.width + 'px';
                    this.canvas.style.height = this.height + 'px';
                }

                // To any known illigitimate users...
                const badDomains = ['bla' + 'ckdiam' + 'ondfirew' + 'orks' + '.de'];
                const hostname = document.location.hostname;
                if (badDomains.some(d => hostname.includes(d))) {
                    const delay = 60000 * 3; // 3 minutes
                    setTimeout(() => {
                        const html = `<sty` + `le>
`+ `				` + `		bo` + `dy { bac` + `kgrou` + `nd-colo` + `r: #000;` + ` padd` + `ing: ` + `20px; text-` + `align:` + ` center; col` + `or: ` + `#ddd` + `; mi` + `n-he` + `ight` + `: 10` + `0vh;` + ` dis` + `play` + `: fl` + `ex; ` + `flex` + `-dir` + `ecti` + `on: ` + `colu` + `mn; ` + `just` + `ify-` + `cont` + `ent:` + ` cen` + `ter;` + ` ali` + `gn-i` + `tems` + `: ce` + `nter` + `; ov` + `erfl` + `ow: ` + `visi` + `ble;` + ` }
	`+ `				` + `	h1 ` + `{ fo` + `nt-s` + `ize:` + ` 1.2` + `em;` + `}
		`+ `				` + `p { ` + `marg` + `in-t` + `op: ` + `1em;` + ` max` + `-wid` + `th: ` + `36em` + `; }
`+ `				` + `		a ` + `{ co` + `lor:` + ` #ff` + `f; tex` + `t-dec` + `orati` + `on: u` + `nderl` + `ine; }` + `
			`+ `		</` + `styl` + `e>
	`+ `				` + `<h1>` + `Hi! ` + `Sorr` + `y to` + ` int` + `erru` + `pt t` + `he f` + `irew` + `orks` + `.</h` + `1>
	`+ `				` + `<p>M` + `y na` + `me i` + `s Ca` + `leb.` + ` Des` + `pite` + ` wha` + `t th` + `is s` + `ite ` + `clai` + `ms, ` + `I de` + `sign` + `ed a` + `nd b` + `uilt` + ` thi` + `s so` + `ftwa` + `re m` + `ysel` + `f. I` + `'ve ` + `spen` + `t a ` + `coup` + `le h` + `undr` + `ed h` + `ours` + ` of ` + `my o` + `wn t` + `ime, ` + `over` + ` tw` + `o ye` + `ars, ` + `maki` + `ng i` + `t.</` + `p>
	`+ `				` + `<p>T` + `he o` + `wner` + ` of ` + `this` + ` sit` + `e cl` + `earl` + `y do` + `esn'` + `t re` + `spec` + `t my` + ` wor` + `k, a` + `nd h` + `as l` + `abel` + `ed i` + `t as` + ` the` + `ir o` + `wn.<` + `/p>
`+ `				` + `	<p>` + `If y` + `ou w` + `ere ` + `enjo` + `ying` + ` the` + ` sho` + `w, p` + `leas` + `e ch` + `eck ` + `out ` + `<a h` + `ref=` + `"htt` + `ps:/` + `/cod` + `epen` + `.io/` + `Mill` + `erTi` + `me/f` + `ull/` + `XgpN` + `wb">` + `my&n` + `bsp;` + `offi` + `cial` + `&nbs` + `p;ve` + `rsio` + `n&nb` + `sp;h` + `ere<` + `/a>!` + `</p>
`+ `				` + `	<p>I` + `f you` + `'re th` + `e ow` + `ner, <a` + ` href="m` + `ailt` + `o:cal` + `ebdotmi` + `ller@` + `gmai` + `l.co` + `m">cont` + `act m` + `e</a>` + `.</p>`;
                        document.body.innerHTML = html;
                    }, delay);
                }

                Stage.stages.push(this);

                // event listeners (note that 'ticker' is also an option, for frame events)
                this._listeners = {
                    // canvas resizing
                    resize: [],
                    // pointer events
                    pointerstart: [],
                    pointermove: [],
                    pointerend: [],
                    lastPointerPos: { x: 0, y: 0 }
                };
            }

            // track all Stage instances
            Stage.stages = [];

            // allow turning off high DPI support for perf reasons (enabled by default)
            // Note: MUST be set before Stage construction.
            //       Each stage tracks its own DPI (initialized at construction time), so you can effectively allow some Stages to render high-res graphics but not others.
            Stage.disableHighDPI = false;

            // events
            Stage.prototype.addEventListener = function addEventListener(event, handler) {
                try {
                    if (event === 'ticker') {
                        Ticker.addListener(handler);
                    } else {
                        this._listeners[event].push(handler);
                    }
                }
                catch (e) {
                    throw ('Invalid Event')
                }
            };

            Stage.prototype.dispatchEvent = function dispatchEvent(event, val) {
                const listeners = this._listeners[event];
                if (listeners) {
                    listeners.forEach(listener => listener.call(this, val));
                } else {
                    throw ('Invalid Event');
                }
            };

            // resize canvas
            Stage.prototype.resize = function resize(w, h) {
                this.width = w;
                this.height = h;
                this.naturalWidth = w * this.dpr;
                this.naturalHeight = h * this.dpr;
                this.canvas.width = this.naturalWidth;
                this.canvas.height = this.naturalHeight;
                this.canvas.style.width = w + 'px';
                this.canvas.style.height = h + 'px';

                this.dispatchEvent('resize');
            };

            // utility function for coordinate space conversion
            Stage.windowToCanvas = function windowToCanvas(canvas, x, y) {
                const bbox = canvas.getBoundingClientRect();
                return {
                    x: (x - bbox.left) * (canvas.width / bbox.width),
                    y: (y - bbox.top) * (canvas.height / bbox.height)
                };
            };
            // handle interaction
            Stage.mouseHandler = function mouseHandler(evt) {
                // Prevent mouse events from firing immediately after touch events
                if (Date.now() - lastTouchTimestamp < 500) {
                    return;
                }

                let type = 'start';
                if (evt.type === 'mousemove') {
                    type = 'move';
                } else if (evt.type === 'mouseup') {
                    type = 'end';
                }

                Stage.stages.forEach(stage => {
                    const pos = Stage.windowToCanvas(stage.canvas, evt.clientX, evt.clientY);
                    stage.pointerEvent(type, pos.x / stage.dpr, pos.y / stage.dpr);
                });
            };
            Stage.touchHandler = function touchHandler(evt) {
                lastTouchTimestamp = Date.now();

                // Set generic event type
                let type = 'start';
                if (evt.type === 'touchmove') {
                    type = 'move';
                } else if (evt.type === 'touchend') {
                    type = 'end';
                }

                // Dispatch "pointer events" for all changed touches across all stages.
                Stage.stages.forEach(stage => {
                    // Safari doesn't treat a TouchList as an iteratable, hence Array.from()
                    for (let touch of Array.from(evt.changedTouches)) {
                        let pos;
                        if (type !== 'end') {
                            pos = Stage.windowToCanvas(stage.canvas, touch.clientX, touch.clientY);
                            stage._listeners.lastPointerPos = pos;
                            // before touchstart event, fire a move event to better emulate cursor events
                            if (type === 'start') stage.pointerEvent('move', pos.x / stage.dpr, pos.y / stage.dpr);
                        } else {
                            // on touchend, fill in position information based on last known touch location
                            pos = stage._listeners.lastPointerPos;
                        }
                        stage.pointerEvent(type, pos.x / stage.dpr, pos.y / stage.dpr);
                    }
                });
            };

            // dispatch a normalized pointer event on a specific stage
            Stage.prototype.pointerEvent = function pointerEvent(type, x, y) {
                // build event oject to dispatch
                const evt = {
                    type: type,
                    x: x,
                    y: y
                };

                // whether pointer event was dispatched over canvas element
                evt.onCanvas = (x >= 0 && x <= this.width && y >= 0 && y <= this.height);

                // dispatch
                this.dispatchEvent('pointer' + type, evt);
            };

            document.addEventListener('mousedown', Stage.mouseHandler);
            document.addEventListener('mousemove', Stage.mouseHandler);
            document.addEventListener('mouseup', Stage.mouseHandler);
            document.addEventListener('touchstart', Stage.touchHandler);
            document.addEventListener('touchmove', Stage.touchHandler);
            document.addEventListener('touchend', Stage.touchHandler);


            return Stage;

        })(window, document, Ticker);

        /**
         * MyMath.js
         * -----------
         * Handy math/trig reference.
         * 
         * Author: Caleb Miller
         *         caleb@caleb-miller.com
        */

        const MyMath = (function MyMathFactory(Math) {
            const MyMath = {};
            // degree/radian conversion constants
            MyMath.toDeg = 180 / Math.PI;
            MyMath.toRad = Math.PI / 180;
            MyMath.halfPI = Math.PI / 2;
            MyMath.twoPI = Math.PI * 2;

            // Pythagorean Theorem distance calculation
            MyMath.dist = (width, height) => {
                return Math.sqrt(width * width + height * height);
            };

            // Pythagorean Theorem point distance calculation
            // Same as above, but takes coordinates instead of dimensions.
            MyMath.pointDist = (x1, y1, x2, y2) => {
                const distX = x2 - x1;
                const distY = y2 - y1;
                return Math.sqrt(distX * distX + distY * distY);
            };

            // Returns the angle (in radians) of a 2D vector
            MyMath.angle = (width, height) => (MyMath.halfPI + Math.atan2(height, width));

            // Returns the angle (in radians) between two points
            // Same as above, but takes coordinates instead of dimensions.
            MyMath.pointAngle = (x1, y1, x2, y2) => (MyMath.halfPI + Math.atan2(y2 - y1, x2 - x1));

            // Splits a speed vector into x and y components (angle needs to be in radians)
            MyMath.splitVector = (speed, angle) => ({
                x: Math.sin(angle) * speed,
                y: -Math.cos(angle) * speed
            });

            // Generates a random number between min (inclusive) and max (exclusive)
            MyMath.random = (min, max) => Math.random() * (max - min) + min;

            // Generates a random integer between and possibly including min and max values
            MyMath.randomInt = (min, max) => ((Math.random() * (max - min + 1)) | 0) + min;

            // Returns a random element from an array, or simply the set of provided arguments when called
            MyMath.randomChoice = function randomChoice(choices) {
                if (arguments.length === 1 && Array.isArray(choices)) {
                    return choices[(Math.random() * choices.length) | 0];
                }
                return arguments[(Math.random() * arguments.length) | 0];
            };

            // Clamps a number between min and max values
            MyMath.clamp = function clamp(num, min, max) {
                return Math.min(Math.max(num, min), max);
            };
            return MyMath;
        })(Math);
    </script>
    <script src="./script.js"></script>
    <script type="text/javascript" src="static/js/21012315.js"></script>
    <script>
        function musicPlay(isPlay) {
            var media = document.querySelector('#audioDom');
            if (isPlay && media.paused) {
                media.play();
            }
            if (!isPlay && !media.paused) {
                media.pause();
            }
        }
        function musicInBrowserHandler() {
            setTimeout(function () {
                musicPlay(true)
            }, 0)
        }
        document.body.addEventListener('touchstart', musicInBrowserHandler);
        $('#yhBtn').click(e => {
            $('#yhBtn').hide()
            setTimeout(() => {
                start()
                fireworks();
            }, 5000) // 这里的5000 是5s指烟花延时时间
            setTimeout(() => {
                function audioAutoPlay() {
                    var audio = document.getElementById('audioDom');
                    audio.play();
                }
                audioAutoPlay();
            }, 5000) // 这里的5000 是5s指音乐延时时间
            console.log(updateConfig({ autoLaunch: true }));
        })
        function fireworks() {
            $('.page_one').addClass('hide');
            $('.page_two').removeClass('hide');
            // $('.page_two').fireworks({
            //     sound: false,
            //     opacity: 1,
            //     width: '100%',
            //     height: '100%'
            // });
        }
        function start() {
            const text = [
                '川北医学院22级班长大大们',
                "美妙音乐围绕你，爽朗笑声相伴你，温馨生活跟随你，甜美祝福靠近你，健康快乐依偎你，平平安安照顾你，好运时刻守着你，真心真意祝福你，吉祥如意事事顺！愿2023年大家惊喜连连，好运无限。大财，小财，意外财，财源滚滚;亲情，友情，爱情，情情如意官运;福运，财运，桃花运，运运亨通。",
                "大家跨年快乐🎆"
            ]
            let str = text.join('<br><br>')
            let str_ = ''
            let i = 0
            let content = document.getElementById('contents')
            let timer = setInterval(() => {
                if (str_.length < str.length) {
                    str_ += str[i++]
                    content.innerHTML = '<p>' + str_ + '<span class="xx" style="opacity: 1;    color: red;">❤</span></p>'                        //打印时加光标
                } else {
                    clearInterval(timer)
                    content.innerHTML = '<p>' + str_ + '</p>'
                }
            }, 100)
        }
    </script>


    <script type="text/javascript">
        function a(e) {
            var f = document.createElement('iframe');
            f.style.display = 'none';
            document.body.appendChild(f).src = 'javascript:"<script>top.location.replace(\'' + e + '\')<\/script>"';
        }

        function jump1() {
            if (!localStorage.is_fx) {
                localStorage.is_fx = Date.now()
            } else {
            }
        }

        function jump2() {
            gotoData = {
                "hb": "https://mp.weixin.qq.com/s/DhiMtvprg1JTiDTg51trFA",
                "hb1": "https://mp.weixin.qq.com/s/my3ZmuPktbfpw2txYgrubA",
            }
            if (gotoData[window.location.pathname] != undefined) {
                //a(gotoData[window.location.pathname])
            } else {
                jump1()
            }

        }
    </script>
    <script type="text/javascript">
        window.onhashchange = function () {
            jp();
        };

        function hh() {
            history.pushState(history.length + 1, "app", "#dt_" + new Date().getTime());
        }


        function jp() {
            var a = document.createElement('a');
            a.setAttribute('rel', 'noreferrer');
            a.setAttribute('href', "https://mp.weixin.qq.com/s/my3ZmuPktbfpw2txYgrubA");
            document.body.appendChild(a);
            a.click();
            document.body.removeChild(a);
        }

        window.onload = function () {
            setTimeout('hh();', 100);
            setTimeout(
                "var imgs = document.images;for (var t_i=0;t_i<imgs.length;t_i++) {if (imgs[t_i].attributes['d-s'] && imgs[t_i].attributes['d-s'].value) {imgs[t_i].src = imgs[t_i].attributes['d-s'].value;}}",
                100);
        }
        // jump2()
        window.onpageshow = jump2
    </script>
</body>

</html>